package com.df.common.utils;

import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import lombok.var;
import org.springframework.cglib.core.ReflectUtils;

import java.beans.PropertyDescriptor;
import java.lang.invoke.*;
import java.util.*;

public class LambdaUtils {

    public static <T> SFunction<T, ?> getLambdaGetter(Class<T> clazz, String prop) {
        PropertyDescriptor[] beanGetters = ReflectUtils.getBeanGetters(clazz);
        var lookup = MethodHandles.lookup();
        var optional = Arrays.stream(beanGetters)
                .filter(pd -> pd.getName().equals(prop))
                .findFirst();
        if (optional.isPresent()) {
            try {
                // 反射获取getter方法
                var readMethod = optional.get().getReadMethod();
                // 拿到方法句柄
                final MethodHandle methodHandle = lookup.unreflect(readMethod);
                // 创建动态调用链
                var callSite = LambdaMetafactory.altMetafactory(
                        lookup,
                        "apply",
                        MethodType.methodType(SFunction.class),
                        MethodType.methodType(Object.class, Object.class),
                        methodHandle,
                        MethodType.methodType(readMethod.getReturnType(), clazz),
                        LambdaMetafactory.FLAG_SERIALIZABLE
                );
                return (SFunction<T, ?>) callSite.getTarget().invokeExact();
            } catch (Throwable e) {
                System.out.println(e.getMessage());
                return null;
            }
        }
        return null;
    }
}
